Check in new formats 'destinator_poi', 'destinator_itn' and 'destinator_trk'.
authoroliskoli <oliskoli>
Thu, 17 Apr 2008 21:57:23 +0000 (21:57 +0000)
committeroliskoli <oliskoli>
Thu, 17 Apr 2008 21:57:23 +0000 (21:57 +0000)
Makefile.in
destinator.c [new file with mode: 0644]
testo
vecs.c

index e97c2d6c3247b7e731f8430e0a0c5cd2a9254156..1746a984e3739221db6e382a24c7502304c16c4a 100644 (file)
@@ -58,7 +58,7 @@ ALL_FMTS=$(MINIMAL_FMTS) gtm.o gpsutil.o pcx.o cetus.o copilot.o \
        yahoo.o unicsv.o wfff_xml.o garmin_txt.o axim_gpb.o gpssim.o \
        wbt-200.o stmsdf.o gtrnctr.o dmtlog.o raymarine.o alan.o vitovtt.o \
        ggv_log.o g7towin.o garmin_gpi.o lmx.o random.o xol.o dg-100.o \
-       navilink.o mtk_logger.o ik3d.o osm.o
+       navilink.o mtk_logger.o ik3d.o osm.o destinator.o
 
 FMTS=@FMTS@
 
diff --git a/destinator.c b/destinator.c
new file mode 100644 (file)
index 0000000..b8d6fec
--- /dev/null
@@ -0,0 +1,588 @@
+/*
+
+    Support for Destinator POI's, Itineraries and Tracklogs.
+    ( as described at "http://mozoft.com/d3log.html" )
+    
+    Copyright (C) 2008 Olaf Klein, o.b.klein@gpsbabel.org
+
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+#include "defs.h"
+#include "cet.h"
+#include "garmin_fs.h"
+#include "strptime.h"
+#include <ctype.h>
+#include <time.h>
+
+#define MYNAME                 "destinator"
+#define DST_DYN_POI    "Dynamic POI"
+#define DST_ITINERARY  "City->Street"
+
+static
+arglist_t destinator_args[] = {
+       ARG_TERMINATOR
+};
+
+static gbfile *fin, *fout;
+static gpsdata_type data_type;
+
+
+/*******************************************************************************/
+/*                                   READER                                    */
+/*-----------------------------------------------------------------------------*/
+
+static garmin_fs_t *
+gmsd_init(waypoint *wpt)
+{
+       garmin_fs_t *gmsd = GMSD_FIND(wpt);
+       if (gmsd == NULL) {
+               gmsd = garmin_fs_alloc(-1);
+               fs_chain_add(&wpt->fs, (format_specific_data *) gmsd);
+       }
+       return gmsd;
+}
+
+static char *
+read_wcstr(const int discard)
+{
+       short *buff = NULL, c;
+       int size = 0, pos = 0;
+       
+       while ((c = gbfgetint16(fin))) {
+               if (size == 0) {
+                       size = 16;
+                       buff = xmalloc(size * 2);
+               }
+               else if (pos == size) {
+                       size += 16;
+                       buff = xrealloc(buff, size * 2);
+               }
+               buff[pos] = c;
+               pos += 1;
+       }
+
+       if (pos != 0) {
+               char *res;
+               if (discard) res = NULL;
+               else {
+                       res = cet_str_uni_to_utf8(buff, pos);
+                       res = lrtrim(res);
+                       if (*res == '\0') {
+                               xfree(res);
+                               res = NULL;
+                       }
+               }
+               xfree(buff);
+               return res;
+       }
+       else
+               return NULL;
+}
+
+static void
+write_wcstr(const char *str)
+{
+       if (str && *str) {
+               int bytes, value;
+               char *cin = (char *)str;
+               char *ce = cin + strlen(cin);
+               while (cin < ce) {
+                       cet_utf8_to_ucs4(cin, &bytes, &value);
+                       cin += bytes;
+                       gbfputint16(value, fout);
+               }
+       }
+       gbfputint16(0, fout);
+}
+
+static int
+read_until_wcstr(const char *str)
+{
+       char *buff;
+       int len, sz;
+       int eos = 0, res = 0;
+       
+       len = strlen(str);
+       sz = (len + 1) * 2;
+       buff = xcalloc(sz, 1);
+       
+       while (! gbfeof(fin)) {
+
+               char c = gbfgetc(fin);
+               memmove(buff, buff + 1, sz - 1);
+               buff[sz - 1] = c;
+
+               if (c == 0) {
+                       eos++;
+                       if (eos >= 2) { /* two or more zero bytes => end of string */
+                               char *test = cet_str_uni_to_utf8((short *)buff, len);
+                               if (test) {
+                                       res = (strcmp(str, test) == 0);
+                                       xfree(test);
+                                       if (res) break;
+                               }
+                       }
+               }
+               else eos = 0;
+       }
+       xfree(buff);
+       return res;
+}
+
+static void
+destinator_read_poi(void)
+{
+       waypoint *wpt;
+       int count = 0;
+       
+       gbfrewind(fin);
+       
+       while (! (gbfeof(fin))) {
+               char *str, *hnum;
+               double ll;
+               garmin_fs_t *gmsd;
+               
+               if (count == 0) {
+                       str = read_wcstr(0);
+                       if ((str == NULL) || (strcmp(str, DST_DYN_POI) != 0))
+                               fatal(MYNAME "_poi: Invalid record header!\n");
+                       xfree(str);
+               }
+               else if (! read_until_wcstr(DST_DYN_POI)) break;
+
+               count++;
+                       
+               wpt = waypt_new();
+               
+               wpt->shortname = read_wcstr(0);
+               wpt->notes = read_wcstr(0);             /* comment */
+
+               hnum = read_wcstr(0);                   /* house number */
+
+               str = read_wcstr(0);                    /* street */
+               if (!str) {
+                       str = hnum;
+                       hnum = NULL;
+               }
+               if (str) {
+                       gmsd = gmsd_init(wpt);
+                       if (hnum) {
+                               str = xstrappend(str, " ");
+                               str = xstrappend(str, hnum);
+                       }
+                       GMSD_SET(addr, str);
+               }
+
+               if ((str = read_wcstr(0))) {            /* city */
+                       gmsd = gmsd_init(wpt);
+                       GMSD_SET(city, str);
+               }
+
+               if (hnum) xfree(hnum);
+
+               (void) read_wcstr(1);                   /* unknown */
+
+               if ((str = read_wcstr(0))) {            /* postcode */
+                       gmsd = gmsd_init(wpt);
+                       GMSD_SET(postal_code, str);
+               }
+
+               (void) read_wcstr(1);                   /* unknown */
+
+               (void) gbfgetdbl(fin);
+               
+               wpt->longitude = gbfgetdbl(fin);
+               wpt->latitude = gbfgetdbl(fin);
+               ll = gbfgetdbl(fin);
+               if (ll != wpt->longitude)
+                       fatal(MYNAME "_poi: Invalid file!\n");
+               ll = gbfgetdbl(fin);
+               if (ll != wpt->latitude)
+                       fatal(MYNAME "_poi: Invalid file!\n");
+               
+               waypt_add(wpt);
+       }
+}
+
+static void
+destinator_read_rte(void)
+{
+       int count = 0;
+       route_head *rte = NULL;
+
+       gbfrewind(fin);
+       
+       while (! (gbfeof(fin))) {
+               char *str;
+               waypoint *wpt;
+               
+               if (count == 0) {
+                       str = read_wcstr(0);
+                       if ((str == NULL) || (strcmp(str, DST_ITINERARY) != 0))
+                               fatal(MYNAME "_itn: Invalid record header!\n");
+                       xfree(str);
+               }
+               else if (! read_until_wcstr(DST_ITINERARY)) break;
+
+               count++;
+               
+               wpt = waypt_new();
+
+               wpt->shortname = read_wcstr(0);
+               wpt->notes = read_wcstr(0);
+
+               (void) gbfgetint32(fin);
+               (void) gbfgetdbl(fin);
+               (void) gbfgetdbl(fin);
+
+               wpt->longitude = gbfgetdbl(fin);
+               wpt->latitude = gbfgetdbl(fin);
+               if (gbfgetdbl(fin) != wpt->longitude)
+                       fatal(MYNAME "_itn: Invalid file!\n");
+               if (gbfgetdbl(fin) != wpt->latitude)
+                       fatal(MYNAME "_itn: Invalid file!\n");
+               
+               if (! rte) {
+                       rte = route_head_alloc();
+                       route_add_head(rte);
+               }
+               route_add_wpt(rte, wpt);
+
+               (void) gbfgetdbl(fin);
+               (void) gbfgetdbl(fin);
+       }
+}
+
+static void
+destinator_read_trk(void)
+{
+       char TXT[4] = "TXT";
+       int recno = -1;
+       route_head *trk = NULL;
+       
+       gbfrewind(fin);
+
+       while (! (gbfeof(fin))) {
+               waypoint *wpt;
+               struct tm tm;
+               char buff[20];
+               int date;
+               double time;
+               
+               recno++;
+               
+               if (gbfeof(fin)) break;
+               
+               wpt = waypt_new();
+
+               wpt->longitude = gbfgetdbl(fin);
+               wpt->latitude = gbfgetdbl(fin);
+               wpt->altitude = gbfgetdbl(fin);
+
+               (void) gbfgetdbl(fin);                          /* unknown */
+               (void) gbfgetdbl(fin);                          /* unknown */
+               (void) gbfgetdbl(fin);                          /* unknown */
+
+               wpt->fix = gbfgetint32(fin);
+               wpt->sat = gbfgetint32(fin);
+
+               gbfseek(fin, 12 * sizeof(gbint32), SEEK_CUR);   /* SAT info */
+
+               date = gbfgetint32(fin);
+               time = gbfgetflt(fin);
+
+               gbfseek(fin, 2 * 12, SEEK_CUR);                 /* SAT info */
+
+               gbfread(TXT, 1, 3, fin);
+               if (strcmp(TXT, "TXT") != 0)
+                       fatal(MYNAME "_trk: No (or unknown) file!\n");
+
+               gbfseek(fin, 13, SEEK_CUR);                     /* unknown */
+
+               memset(&tm, 0, sizeof(tm));
+                       
+               snprintf(buff, sizeof(buff), "%06d%.f", date, time);
+               strptime(buff, "%d%m%y%H%M%S", &tm);
+               wpt->creation_time = mkgmtime(&tm);
+               wpt->microseconds = ((int)time % 1000) * 1000;
+                       
+               if ((wpt->sat > 0) && (wpt->fix > 0)) {
+                       
+                       wpt->fix++;
+                       
+                       if (! trk) {
+                               trk = route_head_alloc();
+                               track_add_head(trk);
+                       }
+                       
+                       track_add_wpt(trk, wpt);
+               }
+               else
+                       waypt_free(wpt);
+       }
+}
+
+static void
+destinator_read(void)
+{
+       int i0, i1;
+       double d0, d1;
+       char buff[16];
+       
+       gbfread(buff, sizeof(buff), 1, fin);
+       i0 = le_read32(&buff[0]);
+       i1 = le_read32(&buff[4]);
+       
+       if ((i0 == 0x690043) && (i1 == 0x790074)) {
+               if (data_type != rtedata)
+                       warning(MYNAME ": Using Desinator Itinerary Format!\n");
+               destinator_read_rte();
+       }
+       else if ((i0 == 0x790044) && (i1 == 0x61006e)) {
+               if (data_type != wptdata)
+                       warning(MYNAME ": Using Desinator POI Format!\n");
+               destinator_read_poi();
+       }
+       else {
+               if (data_type != trkdata)
+                       warning(MYNAME ": Using Desinator Tracklog Format!\n");
+               
+               le_read64(&d0, &buff[0]);
+               le_read64(&d1, &buff[8]);
+               if ((fabs(d0) > 180) || (fabs(d1) > 90))
+                       fatal(MYNAME ": No Destinator (.dat) file!\n");
+               destinator_read_trk();
+       }
+}
+
+/*******************************************************************************/
+/*                                   WRITER                                    */
+/*-----------------------------------------------------------------------------*/
+
+static void
+destinator_wpt_disp(const waypoint *wpt)
+{
+       garmin_fs_t *gmsd = GMSD_FIND(wpt);
+
+       write_wcstr(DST_DYN_POI);
+       write_wcstr((wpt->shortname) ? wpt->shortname : "WPT");
+       write_wcstr((wpt->notes) ? wpt->notes : wpt->description);
+
+       write_wcstr(NULL);                              /* house number */
+       write_wcstr(GMSD_GET(addr, NULL));              /* street */
+       write_wcstr(GMSD_GET(city, NULL));              /* city */
+       write_wcstr(NULL);                              /* unknown */
+       write_wcstr(GMSD_GET(postal_code, NULL));       /* postcode */
+       write_wcstr(NULL);                              /* unknown */
+
+       gbfputint32(0, fout);
+       gbfputint32(0, fout);
+
+       gbfputdbl(wpt->longitude, fout);
+       gbfputdbl(wpt->latitude, fout);
+       gbfputdbl(wpt->longitude, fout);
+       gbfputdbl(wpt->latitude, fout);
+
+       gbfputdbl(0, fout);
+       gbfputdbl(0, fout);
+}
+
+static void
+destinator_trkpt_disp(const waypoint *wpt)
+{
+       int i;
+       
+       gbfputdbl(wpt->longitude, fout);
+       gbfputdbl(wpt->latitude, fout);
+       gbfputdbl(wpt->altitude, fout);
+       gbfputdbl(0, fout);
+       gbfputdbl(0, fout);
+       gbfputdbl(0, fout);
+       gbfputint32(wpt->fix > fix_unknown ? wpt->fix - 1 : 0, fout);
+       gbfputint32(wpt->sat, fout);
+       for (i = 0; i < 12; i++) gbfputint32(0, fout);
+       
+       if (wpt->creation_time) {
+               struct tm tm;
+               double time;
+               int date;
+
+               tm = *gmtime(&wpt->creation_time);
+               tm.tm_mon += 1;
+               tm.tm_year -= 100;
+               date = ((int)tm.tm_mday * 10000) + ((int)tm.tm_mon * 100) + tm.tm_year;
+               gbfputint32(date, fout);
+               
+               time = ((int)tm.tm_hour * 10000) + ((int)tm.tm_min * 100) + tm.tm_sec;
+               time = (time * 1000) + (wpt->microseconds / 1000);
+               gbfputflt(time, fout);
+       }
+       else {
+               gbfputint32(0, fout);   /* Is this invalid ? */
+               gbfputflt(0, fout);
+       }
+
+       for (i = 0; i < 12; i++) gbfputint16(0, fout);
+       gbfputcstr("TXT", fout);
+       for (i = 0; i < 12; i++) gbfputc(0, fout);
+}
+
+static void
+destinator_rtept_disp(const waypoint *wpt)
+{
+       write_wcstr(DST_ITINERARY);
+       write_wcstr((wpt->shortname) ? wpt->shortname : "RTEPT");
+       write_wcstr((wpt->notes) ? wpt->notes : wpt->description);
+
+       gbfputint32(0, fout);
+       gbfputdbl(0, fout);
+       gbfputdbl(0, fout);
+
+       gbfputdbl(wpt->longitude, fout);
+       gbfputdbl(wpt->latitude, fout);
+       gbfputdbl(wpt->longitude, fout);
+       gbfputdbl(wpt->latitude, fout);
+
+       gbfputdbl(0, fout);
+       gbfputdbl(0, fout);
+}
+
+/*******************************************************************************
+* %%%        global callbacks called by gpsbabel main process              %%% *
+*******************************************************************************/
+
+static void
+destinator_rd_init(const char *fname)
+{
+       fin = gbfopen_le(fname, "rb", MYNAME);
+}
+
+static void 
+destinator_rd_deinit(void)
+{
+       gbfclose(fin);
+}
+
+static void
+destinator_read_poi_wrapper(void)
+{
+       data_type = wptdata;
+       destinator_read();
+}
+
+static void
+destinator_read_rte_wrapper(void)
+{
+       data_type = rtedata;
+       destinator_read();
+}
+
+static void
+destinator_read_trk_wrapper(void)
+{
+       data_type = trkdata;
+       destinator_read();
+}
+
+static void
+destinator_wr_init(const char *fname)
+{
+       fout = gbfopen_le(fname, "wb", MYNAME);
+}
+
+static void
+destinator_wr_deinit(void)
+{
+       gbfclose(fout);
+}
+
+static void
+destinator_write_poi(void)
+{
+       waypt_disp_all(destinator_wpt_disp);
+}
+
+static void
+destinator_write_rte(void)
+{
+       route_disp_all(NULL, NULL, destinator_rtept_disp);
+}
+
+static void
+destinator_write_trk(void)
+{
+       track_disp_all(NULL, NULL, destinator_trkpt_disp);
+}
+
+/**************************************************************************/
+
+ff_vecs_t destinator_poi_vecs = {
+       ff_type_file,
+       { 
+               ff_cap_read | ff_cap_write      /* waypoints */, 
+               ff_cap_none                     /* tracks */, 
+               ff_cap_none                     /* routes */
+       },
+       destinator_rd_init,     
+       destinator_wr_init,     
+       destinator_rd_deinit,   
+       destinator_wr_deinit,   
+       destinator_read_poi_wrapper,
+       destinator_write_poi,
+       NULL,
+       destinator_args,
+       CET_CHARSET_UTF8, 1                     /* fixed */
+};
+
+ff_vecs_t destinator_rte_vecs = {
+       ff_type_file,
+       { 
+               ff_cap_none                     /* waypoints */, 
+               ff_cap_none                     /* tracks */, 
+               ff_cap_read | ff_cap_write      /* routes */
+       },
+       destinator_rd_init,     
+       destinator_wr_init,     
+       destinator_rd_deinit,   
+       destinator_wr_deinit,   
+       destinator_read_rte_wrapper,
+       destinator_write_rte,
+       NULL,
+       destinator_args,
+       CET_CHARSET_UTF8, 1                     /* fixed */
+};
+
+ff_vecs_t destinator_trk_vecs = {
+       ff_type_file,
+       { 
+               ff_cap_none                     /* waypoints */, 
+               ff_cap_read | ff_cap_write      /* tracks */, 
+               ff_cap_none                     /* routes */
+       },
+       destinator_rd_init,     
+       destinator_wr_init,     
+       destinator_rd_deinit,   
+       destinator_wr_deinit,   
+       destinator_read_trk_wrapper,
+       destinator_write_trk,
+       NULL,
+       destinator_args,
+       CET_CHARSET_UTF8, 1                     /* fixed */
+};
+
+/**************************************************************************/
diff --git a/testo b/testo
index dcb4d30ae44fd0e6125b83685a0145a3e20587b3..5212800d63c35e8a1c35297c338c599eb75464c3 100755 (executable)
--- a/testo
+++ b/testo
@@ -1308,5 +1308,20 @@ rm -f ${TMPDIR}/osm-*
 ${PNAME} -i osm -f ${REFERENCE}/osm-data.xml -o gpx -F ${TMPDIR}/osm-data.gpx
 compare ${TMPDIR}/osm-data.gpx ${REFERENCE}/osm-data.gpx
 
+# Destinator POI
+${PNAME} -i gpx -f ${REFERENCE}/expertgps.gpx -o destinator_poi -F ${TMPDIR}/destinator_poi.dat
+${PNAME} -i destinator_poi -f ${TMPDIR}/destinator_poi.dat -w -o unicsv,utc=0 -F ${TMPDIR}/destinator_poi.txt
+compare ${TMPDIR}/destinator_poi.txt ${REFERENCE}/destinator_poi.txt
+
+# Destinator Itinerary
+${PNAME} -i gpx -f ${REFERENCE}/expertgps.gpx -o destinator_itn -F ${TMPDIR}/destinator_itn.dat
+${PNAME} -i destinator_itn -f ${TMPDIR}/destinator_itn.dat -r -o unicsv,utc=0 -F ${TMPDIR}/destinator_itn.txt
+compare ${TMPDIR}/destinator_itn.txt ${REFERENCE}/route/destinator_itn.txt
+
+# Destinator TrackLog
+${PNAME} -i nmea -f ${REFERENCE}/track/nmea+ms.txt -o destinator_trk -F ${TMPDIR}/destinator_trk.dat
+${PNAME} -i destinator_trk -f ${TMPDIR}/destinator_trk.dat -t -o unicsv,utc=0 -F ${TMPDIR}/destinator_trk.txt
+compare ${TMPDIR}/destinator_trk.txt ${REFERENCE}/track/destinator_trk.txt
+
 
 exit 0
diff --git a/vecs.c b/vecs.c
index e3169f184c0ddf0f7b6de55d777dcd9871f30ac9..506ae0ae881624320aa1b383e614a541846f2df2 100644 (file)
--- a/vecs.c
+++ b/vecs.c
@@ -132,6 +132,9 @@ extern ff_vecs_t xol_vecs;
 extern ff_vecs_t navilink_vecs;
 extern ff_vecs_t ik3d_vecs;
 extern ff_vecs_t osm_vecs;
+extern ff_vecs_t destinator_poi_vecs;
+extern ff_vecs_t destinator_trk_vecs;
+extern ff_vecs_t destinator_rte_vecs;
 
 static
 vecs_t vec_list[] = {
@@ -739,6 +742,24 @@ vecs_t vec_list[] = {
                 "OpenStreetMap data files",
                 "xml"
         },
+        {
+                &destinator_poi_vecs,
+                "destinator_poi",
+                "Destinator Points of Interest (.dat)",
+                "dat"
+        },
+        {
+                &destinator_rte_vecs,
+                "destinator_itn",
+                "Destinator Itineraries (.dat)",
+                "dat"
+        },
+        {
+                &destinator_trk_vecs,
+                "destinator_trk",
+                "Destinator TrackLogs (.dat)",
+                "dat"
+        },
 #endif // MAXIMAL_ENABLED
        {
                NULL,